环境装怕了,还是用 docker 吧

环境装怕了,还是用 docker 吧

三月 24, 2019

前因

除了兴趣,很多时候技能也是跟着需求走的;这一次某站需要迁移服务器,由于某些原因,接手了这个工作,迁移工作比想象中的麻烦的多,全部项目都没有文档,只有几个服务器 IP 账号密码。。好吧,只能一个个找了。

使用 Chrome 浏览器的 Wappalyzer 插件可以看到服务器使用了 Nginx 反向代理(也可以 whereis nginx 看下),那就好办多了,查看配置文件就可以知道项目所在。

为了避免不必要的麻烦,各环境都尽量装相同或者接近的版本。这次迁移比较特殊,因为不能保证迁移完成后无需再迁移。我想大家都不想一遍又一遍的安装环境吧,当然自己编写安装脚本也是可以的。
另外,使用 docker 的话,也可以很好的解决这个问题,DockerHub 每个账号也可以有一个免费的私有仓库,做好容器后 push,新服务器再 pull 下来,很是方便。

docker 大名好久以前就听过,但是一直都没有去接触,这次需求来了,我的一贯做法是先去花点时间简单入个门,然后开始上手,遇到问题再具体搜索相应的解决办法。

安装 Docker

以下安装方法是直接 Copy 的,服务器是 CentOS 7。

从 2017 年 3 月开始 docker 在原来的基础上分为两个分支版本: Docker CE 和 Docker EE。
Docker CE 即社区免费版,Docker EE 即企业版,强调安全,但需付费使用。
本文介绍 Docker CE 的安装使用。

移除旧的版本:

1
2
3
4
5
6
7
8
9
10
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

安装一些必要的系统工具:

1
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

添加软件源信息:

1
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新 yum 缓存:

1
sudo yum makecache fast

安装 Docker-ce:

1
sudo yum -y install docker-ce

启动 Docker 后台服务

1
sudo systemctl start docker

测试运行 hello-world (由于本地没有hello-world这个镜像,所以会下载一个hello-world的镜像,并在容器内运行。)

1
docker run hello-world

使用过程中的小记

  • 登录
    docker login

  • 把远程仓库的容器下载下来
    docker pull xx/centos

  • 创建bridge网络:(多个容器之间互相访问的其中一个做法)
    docker network create dbnet

  • 自启动(docker服务重启后容器也自动重启)
    --restart=always

  • 如果已经启动了则可以使用如下命令:
    docker update *--restart=always <CONTAINER ID>*

  • 解决容器内 Nginx 无法获取到用户的真实IP
    --net=host

  • 端口,可以多个
    -p 80:80 -p 3306:3306

  • 把容器里的 /home 挂载到宿主的 /home(这样项目目录的数据就放在了宿主挂载点上)
    -v /home:/home

  • 运行容器
    我的实例(- -!)还是方便以后自己再看的时候,所以文章我并不是要写成教学
    主站我是把数据库和主环境分开各自弄了个容器,数据库的配置(方便修改配置,因为是直接 pull 的数据库,进入容器也是修改不了,因为 vi 也用不了)和数据文件也是挂载到了宿主目录上

    • 数据库(如果挂载有数据的数据卷时,可以不用 MYSQL_ROOT_PASSWORD 这个参数。)运行成功后,迁移数据库的话,我是用 Navicat(win 版才好用) 进行迁移的。
      docker run -d -p 3306:3306 --net=host -e MYSQL_ROOT_PASSWORD=xxxxxxxxxx -v /home/data/mariadb:/var/lib/mysql -v /etc/mysql:/etc/mysql --restart=always mariadb

    • 主环境
      docker run -it -d --net=host --privileged=true -v /home:/home --restart=always xx/centos:v1.0 /bin/bash
      xx/centos:v1.0 是容器镜像的名字版本,我是基于 centos 容器做的,在容器里面装好各种环境,确保运行最新的版本,可通过如下命令查看

      1
      2
      3
      4
      5
      6
      7
      8
      9
      [nukc@ec ~]# docker images
      REPOSITORY TAG IMAGE ID CREATED SIZE
      xx/centos v1.3 a6f21ddb92db 3 days ago 23.9GB
      xx/centos v1.2 1f948192ecaa 6 days ago 23.3GB
      xx/centos v1.1 adcf4b959180 8 days ago 23.1GB
      xx/centos v1 6a287c9345db 9 days ago 22.9GB
      xx/centos latest 82c6154682c9 10 days ago 22.9GB
      mariadb latest e93652b8b80d 12 days ago 368MB
      centos centos6 0cbf37812bff 5 months ago 194MB

      大小很大,唉,还是不吐槽他们的项目开发了

      如下命令可以看到正在运行的容器,加上 -a 可以看到全部,因为是使用 --net=host,所以 PORTS 是看不到的

      1
      2
      3
      4
      [nukc@ec ~]# docker ps
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      427baa8ca92a mariadb "docker-entrypoint.s…" 36 hours ago Up 36 hours unruffled_feistel
      f40bb958b69e xx/centos:v1.3 "/bin/bash" 36 hours ago Up 36 hours vibrant_noether

      进入容器内,f40bb958b69 为 CONTAINER ID
      docker exec -it f40bb958b69e /bin/bash

      保存容器镜像,一般都是只修改版本,当然也可以改成另一个名字,当然修改后别忘了 push 到仓库上
      docker commit f40bb958b69 xx/centos:v1.4

    • App 的服务器

      我最先迁移的就是 App 的服务器,这个我是把数据库和主环境都塞进了一个容器中
      docker run -it -d --net=host xx/xxx:ban

  • 关于重启容器后,各容器内的服务都没有自动启动的问题
    虽然我已经是 chkconfig xx on 进行了设置,但并没有达到目的,目前每次都是 run 容器后,再 exec 进入启动相应的服务,比如

    • App

      1
      2
      3
      4
      service nginx restart
      service php-fpm start
      service mysqld start
      redis-server /etc/redis.conf
    • 主站

      1
      2
      service nginx restart
      service php-fpm start

      因为主站的数据库是容器分开,直接 run 挂载数据库文件和配置就可以了。

      服务随容器启动而自启动需要另外花时间研究,目前有想过写个简单的启动脚本,然后再 run 的时候执行这个脚本

后果

虽然刚开始花了点时间,但是收获还是很值得的,要是服务器再炸了,直接 pull 就完事了